 /// @file InterOpGDT.h
 /// @brief InterOpGDT 
 /// @copyright Copyright (c) 2025  Hefei Jiushao Intelligent Technology Co., Ltd. All rights reserved.
 /// @createtime 2025-04-07

#ifndef INTEROPGDT_H
#define INTEROPGDT_H
#include "InterOpPMIBase.h"
#include <memory>
#include <vector>
#include "InterOpPMIDatum.h"
#include "pmi/InterOpPMIBase.h"

namespace  AMCAX::Exchange::InterOp::PMI {

enum class PMIToleranceType{
    UNKNOWN,

	// Form tolerance
	Form_Straightness,			  /**< Form_Straightness */
	Form_Flatness,				  /**< Form_Flatness */
	Form_Circularity,				  /**< Form_Circularity */
	Form_Cylindricity,			  /**< Form_Cylindricity */
	Form_ProfileAnyLine,			  /**< Form_ProfileAnyLine */
	Form_ProfileAnySurface,		  /**< Form_ProfileAnySurface */

	// Orientation tolerance
	Orientation_Parallelism,		  /**< Orientation_Parallelism */
	Orientation_Perpendicularity,	  /**< Orientation_Perpendicularity */
	Orientation_Angularity,		  /**< Orientation_Angularity */
											  /**<  */
	// Position tolerance
	Location_TruePosition,		  /**< Location_TruePosition */
	Location_Concentricity,		  /**< Location_Concentricity */
	Location_Coaxiality,			  /**< Location_Coaxiality */
	Location_Symmetry,			  /**< Location_Symmetry */
	Location_PositionOfAnyLine,	  /**< Location_PositionOfAnyLine */
	Location_PositionOfASurface,	  /**< Location_PositionOfASurface */

	// Run-out tolerance
	RunOut_Circular,				 /**< RunOut_Circular	*/
	RunOut_Total					 /**< RunOut_Total */
} ;

enum class PMIToleranceValueType{
    NONE,
    DIAMETER,
    RADIUS,
    SPHERICAL,
    SQUARE,
} ;

enum class PMIToleranceModifierType{
    NoModifier,								/**< NoModifier */

	// Material conditions.
	MaterialCondition_Unsupported,			/**< MaterialCondition_Unsupported */
	MaterialCondition_NoModifier,				/**< MaterialCondition_NoModifier */
	MaterialCondition_Maximum,				/**< MaterialCondition_Maximum */
	MaterialCondition_Least,					/**< MaterialCondition_Least */
	MaterialCondition_RegardlessOfFeatureSize,/**< MaterialCondition_RegardlessOfFeatureSize */

	// Tangent planes
	TangentPlane_Unsupported,					/**< TangentPlane_Unsupported */
	TangentPlane_NotTangent,					/**< TangentPlane_NotTangent */
	TangentPlane_Tangent,						/**< TangentPlane_Tangent */

	// Free State
	FreeState_Unsupported,					/**< FreeState_Unsupported */
	FreeState_Free,							/**< FreeState_Free */
	FreeState_NotFree,						/**< FreeState_NotFree */

	//ST symbol
	Statistical_Symbol,						/**< Statistical_Symbol */

	//Common Zone
	CommonZone,								/**< CommonZone */


	//Unequally Disposed Tolerance Zone
	UnequallyDisposedZone,						/**< UnequallyDisposedZone */

	// Projected State
	ProjectedState_Projected,					/**< ProjectedState_Projected */
	ProjectedState_NotProjected,				/**< ProjectedState_NotProjected */

	// Circle U 
	CircleU,									/**< CircleU */

	Maximum,									/**< Maximum */
	MinimaxFeature,							/**< MinimaxFeature */
	DerivedFeature,							/**< DerivedFeature */
	DynamicProfile,							/**< DynamicProfile */
	LeastSquareFeature,						/**< LeastSquareFeature */
	MaximumInscribedFeature,					/**< MaximumInscribedFeature */
	MinimumCircumscribedFeature,				/**< MinimumCircumscribedFeature */

	SeparateZone,									/*SeparateZone*/
	OffsetZone,									/*OffsetZone*/
	VariableAngle,								/*VariableAngle*/
	OrientationConstraint,						/*OrientationConstraint*/
	MinimaxAssociation,							/*MinimaxAssociation*/
	MinimaxAssociationWithExternalConstraint,		/*MinimaxAssociationWithExternalConstraint*/
	MinimaxAssociationWithInternalConstraint,		/*MinimaxAssociationWithInternalConstraint*/
	LeastSquareAssociation,						/*LeastSquareAssociation*/
	LeastSquareAssociationWithExternalConstraint, /*LeastSquareAssociationWithExternalConstraint*/
	LeastSquareAssociationWithInternalConstraint, /*LeastSquareAssociationWithInternalConstraint*/
	MinimumCircumscribedAssociation,				/*MinimumCircumscribedAssociation*/
	MaximumInscribedAssociation,					/*MaximumInscribedAssociation*/
	TotalRangeOfDeviations,						/*TotalRangeOfDeviations*/
	PeakHeight,									/*PeakHeight*/
	ValleyDepth,									/*ValleyDepth*/
	StandardDeviation								/*StandardDeviation*/
} ;

class PMIZoneModifier {
public:
    PMIZoneModifier() = default ;
    void SetZoneModifierType(const PMIToleranceModifierType &t){
        this->zoneModifierType = t ; 
    } ;
    void SetZoneModifierMagnitudeValue(double t){
        this->zoneModifierMagnitudeValue = t ; 
    } ;
    PMIToleranceModifierType GetZoneModifierType() const {
        return zoneModifierType;
    }

    double GetZoneModifierMagnitudeValue() const {
        return zoneModifierMagnitudeValue;
    }
private:
    PMIToleranceModifierType zoneModifierType ;
    double zoneModifierMagnitudeValue ;
} ;

class PMIModifiedDatum{
public:
    void AddZoneModifier(const PMIZoneModifier &zoneModifier) {
        this->zoneModifiers.push_back(zoneModifier) ;
    }
    const std::vector<PMIZoneModifier>& GetZoneModifiers() const {
        return zoneModifiers;
    }
private:
    std::vector<PMIZoneModifier> zoneModifiers ;
} ;

class DatumRef {

public:
    // struct ModifiedDatum{
    //     InterOpDatum datum ;
    //     PMIToleranceModifierType modifierType ;
    // } ;

    void SetLabel(const std::string & l){
        this->label = l ;
    } ;

    void SetText(const InterOpPMIText &t){
        this->text = t ;
    }

    void AddModifierDatum(const PMIModifiedDatum &pmiModifierDatum){
        this->pmiModifierDatums.push_back(pmiModifierDatum) ;
    }

    const std::string& GetLabel() const {
        return label;
    }

    const InterOpPMIText& GetText() const {
        return text;
    }

    const std::vector<PMIModifiedDatum>& GetModifierDatums() const {
        return pmiModifierDatums;
    }
private:
    std::string label ;
    InterOpPMIText text ;
    std::vector<PMIModifiedDatum> pmiModifierDatums ;
} ;

class GDTRefFrame{
public:
    void SetLabel(const std::string &label){
        this->label = label ; 
    } ;
    void AddDatumRef(const std::shared_ptr<DatumRef> &datumRef){
        this->datumRefs.push_back(datumRef) ;
    } ;
    const std::string& GetLabel() const {
        return label;
    }

    const std::vector<std::shared_ptr<DatumRef>>& GetDatumRefs() const {
        return datumRefs;
    }
private:
    std::string label ;
    std::vector<std::shared_ptr<DatumRef>> datumRefs ;
} ;

class InterOpGDTRow
{
public:
    void SetToleranceValueType(const PMIToleranceValueType &t){
        this->modifierType = t ; 
    } ;

    void SetToleranceValue(double t){
        this->toleranceMagnitudeValue = t ; 
    } ;
    void SetRefinementToleranceValue(double t){
        this->refinementToleranceValue = t ; 
    } ;
    void SetRateUnit1(double t){
        this->rateUnit1 = t ; 
    } ;
    void SetRateUnit2(double t){
        this->rateUnit2 = t ; 
    } ;
    void AddZoneModifier(const PMIZoneModifier &zoneModifier){
        this->zoneModifiers.push_back(zoneModifier) ;
    } ;

    void SetGDTRefFrame(const std::shared_ptr<GDTRefFrame> &gdtRefFrame){
        this->gdtRefFrame = gdtRefFrame ;
    } ;
    PMIToleranceValueType GetToleranceValueType() const {
        return modifierType;
    }

    double GetToleranceValue() const {
        return toleranceMagnitudeValue;
    }

    double GetRefinementToleranceValue() const {
        return refinementToleranceValue;
    }

    double GetRateUnit1() const {
        return rateUnit1;
    }

    double GetRateUnit2() const {
        return rateUnit2;
    }

    const std::vector<PMIZoneModifier>& GetZoneModifiers() const {
        return zoneModifiers;
    }

    std::shared_ptr<GDTRefFrame> GetGDTRefFrame() const {
        return gdtRefFrame;
    }
private:
    PMIToleranceValueType modifierType ;
    double toleranceMagnitudeValue ;
    double refinementToleranceValue ;
    double rateUnit1 ;
    double rateUnit2 ;
    std::vector<PMIZoneModifier> zoneModifiers ;

    std::shared_ptr<GDTRefFrame> gdtRefFrame ;
} ;
    
#define IS_InterOpGDT(BasePtr) IS_DERIVED_SHARED_PTR(BasePtr, AMCAX::Exchange::InterOp::PMI::InterOpGDT)
#define Cast_InterOpGDT(BasePtr) SAFE_SHARED_PTR_CAST(BasePtr, AMCAX::Exchange::InterOp::PMI::InterOpGDT)
class InterOpGDT : public InterOpPMIAnnotation
{
public:
    PMIAnnotationType GetType() const override
	{
		return PMIAnnotationType::GDT;
	} 

    void SetToleranceType(const PMIToleranceType &t){
        this->toleranceType = t ; 
    } ;
    void SetToleranceValueType(const PMIToleranceValueType &t){
        this->valueType = t ; 
    } ;
    void SetToleranceValue(double t){
        this->toleranceValue = t ; 
    } ;
    void SetRefinementToleranceValue(double t){
        this->refinementToleranceValue = t ; 
    } ;
    void SetRateUnit1(double t){
        this->rateUnit1 = t ; 
    } ;
    void SetRateUnit2(double t){
        this->rateUnit2 = t ; 
    } ;
    void SetProjectedToleranceLength(double t){
        this->projectedToleranceLength = t ; 
    } ;
    void SetProfileShiftValue(double t){
        this->profileShiftValue = t ; 
    } ;
    void SetAllAround(bool t){
        this->allAround = t ; 
    } ;
    void SetNote(const std::string &t){
        this->note = t ; 
    } ;
    void SetNoteText(const InterOpPMIText &t){
        this->noteText = t ; 
    } ;

    void AddGDTRow(const InterOpGDTRow &gdtRow){
        this->gdtRows.push_back(gdtRow) ;
    } ;

    PMIToleranceType GetToleranceType() const {
        return toleranceType;
    }

    PMIToleranceValueType GetToleranceValueType() const {
        return valueType;
    }

    double GetToleranceValue() const {
        return toleranceValue;
    }

    double GetRefinementToleranceValue() const {
        return refinementToleranceValue;
    }

    double GetRateUnit1() const {
        return rateUnit1;
    }

    double GetRateUnit2() const {
        return rateUnit2;
    }

    double GetProjectedToleranceLength() const {
        return projectedToleranceLength;
    }

    double GetProfileShiftValue() const {
        return profileShiftValue;
    }

    bool GetAllAround() const {
        return allAround;
    }

    const std::string& GetNote() const {
        return note;
    }

    const InterOpPMIText& GetNoteText() const {
        return noteText;
    }

    const std::vector<InterOpGDTRow>& GetGDTRows() const {
        return gdtRows;
    }
private:
    PMIToleranceType toleranceType ;
    PMIToleranceValueType valueType ;
    double toleranceValue ;
    double refinementToleranceValue ;
    double rateUnit1 ;
    double rateUnit2 ;
    double projectedToleranceLength ;
    double profileShiftValue ;
    bool allAround ;
    std::string note ;

    InterOpPMIText noteText ;

    std::vector<InterOpGDTRow> gdtRows ;

    
} ;

}
#endif